<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 5.4.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/blog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/blog/css/main.css">



<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.2/css/all.min.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css">

<script class="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"littlefxc.github.io","root":"/blog/","images":"/blog/images","scheme":"Mist","version":"8.2.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":false,"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/blog/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}};
  </script>
<meta name="description" content="转载自https:&#x2F;&#x2F;juejin.cn&#x2F;post&#x2F;6844903874927525902#heading-21  什么是Redis持久化? Redis作为一个键值对内存数据库(NoSQL)，数据都存储在内存当中，在处理客户端请求时，所有操作都在内存当中进行，如下所示：  这样做有什么问题呢？">
<meta property="og:type" content="article">
<meta property="og:title" content="理解Redis的持久化机制:RDB&amp;AOF">
<meta property="og:url" content="http://littlefxc.github.io/2020/12/24/%E7%90%86%E8%A7%A3Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%9C%BA%E5%88%B6-RDB-AOF/index.html">
<meta property="og:site_name" content="一年春又来">
<meta property="og:description" content="转载自https:&#x2F;&#x2F;juejin.cn&#x2F;post&#x2F;6844903874927525902#heading-21  什么是Redis持久化? Redis作为一个键值对内存数据库(NoSQL)，数据都存储在内存当中，在处理客户端请求时，所有操作都在内存当中进行，如下所示：  这样做有什么问题呢？">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_1.jpg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_2.jpg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_3.jpg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_4.jpg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_5.jpg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_6.jpg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_7.jpg">
<meta property="og:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_8.jpg">
<meta property="article:published_time" content="2020-12-24T03:33:37.000Z">
<meta property="article:modified_time" content="2021-03-25T13:15:49.000Z">
<meta property="article:author" content="一年春又来">
<meta property="article:tag" content="redis">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_1.jpg">


<link rel="canonical" href="http://littlefxc.github.io/2020/12/24/%E7%90%86%E8%A7%A3Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%9C%BA%E5%88%B6-RDB-AOF/">


<script class="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>
<title>理解Redis的持久化机制:RDB&AOF | 一年春又来</title>
  




  <noscript>
  <style>
  body { margin-top: 2rem; }

  .use-motion .menu-item,
  .use-motion .sidebar,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header {
    visibility: visible;
  }

  .use-motion .header,
  .use-motion .site-brand-container .toggle,
  .use-motion .footer { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle,
  .use-motion .custom-logo-image {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line {
    transform: scaleX(1);
  }

  .search-pop-overlay, .sidebar-nav { display: none; }
  .sidebar-panel { display: block; }
  </style>
</noscript>

<link rel="alternate" href="/blog/atom.xml" title="一年春又来" type="application/atom+xml">
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/blog/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">一年春又来</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu">
        <li class="menu-item menu-item-home"><a href="/blog/" rel="section"><i class="home                          //首页 fa-fw"></i>首页</a></li>
        <li class="menu-item menu-item-archives"><a href="/blog/archives/" rel="section"><i class="archive          //归档 fa-fw"></i>归档</a></li>
        <li class="menu-item menu-item-categories"><a href="/blog/categories/" rel="section"><i class="th           //分类 fa-fw"></i>分类</a></li>
        <li class="menu-item menu-item-tags"><a href="/blog/tags/" rel="section"><i class="tags                     //标签 fa-fw"></i>标签</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AFRedis%E6%8C%81%E4%B9%85%E5%8C%96"><span class="nav-text">什么是Redis持久化?</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#RDB"><span class="nav-text">RDB</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%80%E5%90%AFRDB%E6%8C%81%E4%B9%85%E5%8C%96%E6%96%B9%E5%BC%8F"><span class="nav-text">开启RDB持久化方式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-save%E5%91%BD%E4%BB%A4"><span class="nav-text">1. save命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-bgsave"><span class="nav-text">2. bgsave</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%85%8D%E7%BD%AE%E8%87%AA%E5%8A%A8%E8%A7%A6%E5%8F%91"><span class="nav-text">3. 服务器配置自动触发</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#rdb%E6%96%87%E4%BB%B6"><span class="nav-text">rdb文件</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#RDB%E7%9A%84%E5%87%A0%E4%B8%AA%E4%BC%98%E7%82%B9"><span class="nav-text">RDB的几个优点</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#RDB%E7%9A%84%E5%87%A0%E4%B8%AA%E7%BC%BA%E7%82%B9"><span class="nav-text">RDB的几个缺点</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#AOF"><span class="nav-text">AOF</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%80%E5%90%AFAOF%E6%8C%81%E4%B9%85%E5%8C%96%E6%96%B9%E5%BC%8F"><span class="nav-text">开启AOF持久化方式</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%89%E7%A7%8D%E5%86%99%E5%85%A5%E7%AD%96%E7%95%A5"><span class="nav-text">三种写入策略</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-always"><span class="nav-text">1. always</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-everysec"><span class="nav-text">2. everysec</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-no"><span class="nav-text">3. no</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AOF%E6%96%87%E4%BB%B6%E9%87%8D%E5%86%99"><span class="nav-text">AOF文件重写</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%B8%A4%E7%A7%8D%E9%87%8D%E5%86%99%E6%96%B9%E5%BC%8F"><span class="nav-text">两种重写方式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%87%8D%E5%86%99aof%E6%96%87%E4%BB%B6%E7%9A%84%E5%A5%BD%E5%A4%84"><span class="nav-text">重写aof文件的好处</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AOF%E6%96%87%E4%BB%B6%E6%8D%9F%E5%9D%8F"><span class="nav-text">AOF文件损坏</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AOF%E7%9A%84%E4%BC%98%E7%82%B9"><span class="nav-text">AOF的优点</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#AOF%E7%9A%84%E7%BC%BA%E7%82%B9"><span class="nav-text">AOF的缺点</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E9%80%89%E6%8B%A9RDB%E8%BF%98%E6%98%AFAOF%E5%91%A2%EF%BC%9F"><span class="nav-text">选择RDB还是AOF呢？</span></a></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%B0%8F%E7%BB%93"><span class="nav-text">小结</span></a></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">一年春又来</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/blog/archives/">
        
          <span class="site-state-item-count">184</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/blog/categories/">
          
        <span class="site-state-item-count">35</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/blog/tags/">
          
        <span class="site-state-item-count">115</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>



        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://littlefxc.github.io/2020/12/24/%E7%90%86%E8%A7%A3Redis%E7%9A%84%E6%8C%81%E4%B9%85%E5%8C%96%E6%9C%BA%E5%88%B6-RDB-AOF/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/blog/images/avatar.gif">
      <meta itemprop="name" content="一年春又来">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="一年春又来">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          理解Redis的持久化机制:RDB&AOF
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2020-12-24 11:33:37" itemprop="dateCreated datePublished" datetime="2020-12-24T11:33:37+08:00">2020-12-24</time>
    </span>
      <span class="post-meta-item">
        <span class="post-meta-item-icon">
          <i class="far fa-calendar-check"></i>
        </span>
        <span class="post-meta-item-text">更新于</span>
        <time title="修改时间：2021-03-25 21:15:49" itemprop="dateModified" datetime="2021-03-25T21:15:49+08:00">2021-03-25</time>
      </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/blog/categories/redis/" itemprop="url" rel="index"><span itemprop="name">redis</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <blockquote>
<p>转载自<a target="_blank" rel="noopener" href="https://juejin.cn/post/6844903874927525902#heading-21">https://juejin.cn/post/6844903874927525902#heading-21</a></p>
</blockquote>
<h1 id="什么是Redis持久化"><a href="#什么是Redis持久化" class="headerlink" title="什么是Redis持久化?"></a>什么是Redis持久化?</h1><hr>
<p><code>Redis</code>作为一个键值对内存数据库(<code>NoSQL</code>)，数据都存储在内存当中，在处理客户端请求时，所有操作都在内存当中进行，如下所示：</p>
<p><img src="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_1.jpg" alt="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_1.jpg"></p>
<p>这样做有什么问题呢？</p>
<span id="more"></span>

<p>其实，只要稍微有点计算机基础知识的人都知道，存储在内存当中的数据，只要服务器关机(各种原因引起的)，内存中的数据就会消失了，不仅服务器关机会造成数据消失，<code>Redis</code>服务器守护进程退出，内存中的数据也一样会消失。</p>
<p><img src="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_2.jpg" alt="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_2.jpg"></p>
<p>于只把<code>Redis</code>当缓存来用的项目来说，数据消失或许问题不大，重新从数据源把数据加载进来就可以了，但如果直接把用户提交的业务数据存储在<code>Redis</code>当中，把<code>Redis</code>作为数据库来使用，在其放存储重要业务数据，那么<code>Redis</code>的内存数据丢失所造成的影响也许是毁灭性。</p>
<p>为了避免内存中数据丢失，Redis提供了对持久化的支持，我们可以选择不同的方式将数据从内存中保存到硬盘当中，使数据可以持久化保存。</p>
<p><img src="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_3.jpg" alt="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_3.jpg"></p>
<p>Redis提供了RDB和AOF两种不同的数据持久化方式，下面我们就来详细介绍一下这种不同的持久化方式吧。</p>
<h1 id="RDB"><a href="#RDB" class="headerlink" title="RDB"></a>RDB</h1><hr>
<p><code>RDB</code>是一种快照存储持久化方式，具体就是将Redis某一时刻的内存数据保存到硬盘的文件当中，默认保存的文件名为<code>dump.rdb</code>，而在<code>Redis</code>服务器启动时，会重新加载<code>dump.rdb</code>文件的数据到内存当中恢复数据。</p>
<h2 id="开启RDB持久化方式"><a href="#开启RDB持久化方式" class="headerlink" title="开启RDB持久化方式"></a>开启RDB持久化方式</h2><p>开启<code>RDB</code>持久化方式很简单，客户端可以通过向<code>Redis</code>服务器发送<code>save</code>或<code>bgsave</code>命令让服务器生成<code>rdb</code>文件，或者通过服务器配置文件指定触发<code>RDB</code>条件。</p>
<h3 id="1-save命令"><a href="#1-save命令" class="headerlink" title="1. save命令"></a>1. save命令</h3><p><code>save</code>命令是一个同步操作。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 同步数据到磁盘上</span></span><br><span class="line">&gt; save</span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_4.jpg" alt="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_4.jpg"></p>
<p><strong>当客户端向服务器发送<code>save</code>命令请求进行持久化时，服务器会阻塞<code>save</code>命令之后的其他客户端的请求，直到数据同步完成。</strong></p>
<p>如果数据量太大，同步数据会执行很久，而这期间Redis服务器也无法接收其他请求，所以，最好不要在生产环境使用save命令。</p>
<h3 id="2-bgsave"><a href="#2-bgsave" class="headerlink" title="2. bgsave"></a>2. bgsave</h3><p>与<code>save</code>命令不同，<code>bgsave</code>命令是一个异步操作。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 异步保存数据集到磁盘上</span></span><br><span class="line">&gt; bgsave</span><br></pre></td></tr></table></figure>

<p><img src="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_5.jpg" alt="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_5.jpg"></p>
<p>当客户端发服务发出<code>bgsave</code>命令时，<code>Redis</code>服务器主进程会<code>forks</code>一个子进程来数据同步问题，在将数据保存到rdb文件之后，子进程会退出。</p>
<p>所以，与<code>save</code>命令相比，<code>Redis</code>服务器在处理<code>bgsave</code>采用子线程进行IO写入，而主进程仍然可以接收其他请求，但<code>forks</code>子进程是同步的，所以<code>forks</code>子进程时，一样不能接收其他请求，这意味着，<strong>如果forks一个子进程花费的时间太久(一般是很快的)，<code>bgsave</code>命令仍然有阻塞其他客户的请求的情况发生。</strong></p>
<h3 id="3-服务器配置自动触发"><a href="#3-服务器配置自动触发" class="headerlink" title="3. 服务器配置自动触发"></a>3. 服务器配置自动触发</h3><p>除了通过客户端发送命令外，还有一种方式，就是在<code>Redis</code>配置文件中的<code>save</code>指定到达触发RDB持久化的条件，比如【多少秒内至少达到多少写操作】就开启<code>RDB</code>数据同步。</p>
<p>例如我们可以在配置文件<code>redis.conf</code>指定如下的选项：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 900s内至少达到一条写命令</span><br><span class="line">save 900 1</span><br><span class="line"># 300s内至少达至10条写命令</span><br><span class="line">save 300 10</span><br><span class="line"># 60s内至少达到10000条写命令</span><br><span class="line">save 60 10000</span><br></pre></td></tr></table></figure>

<p>之后在启动服务器时加载配置文件。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 启动服务器加载配置文件</span></span><br><span class="line">redis-server redis.conf</span><br></pre></td></tr></table></figure>

<p>这种通过服务器配置文件触发RDB的方式，与bgsave命令类似，达到触发条件时，会forks一个子进程进行数据同步，不过<strong>最好不要通过这方式来触发RDB持久化，因为设置触发的时间太短，则容易频繁写入rdb文件，影响服务器性能，时间设置太长则会造成数据丢失</strong>。</p>
<h2 id="rdb文件"><a href="#rdb文件" class="headerlink" title="rdb文件"></a>rdb文件</h2><p>前面介绍了三种让服务器生成rdb文件的方式，无论是由主进程生成还是子进程来生成，其过程如下：</p>
<ol>
<li>生成临时rdb文件，并写入数据。</li>
<li>完成数据写入，用临时文代替代正式rdb文件。</li>
<li>删除原来的db文件。</li>
</ol>
<p>RDB默认生成的文件名为dump.rdb，当然，我可以通过配置文件进行更加详细配置，比如在单机下启动多个redis服务器进程时，可以通过端口号配置不同的rdb名称，如下所示：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 是否压缩rdb文件</span><br><span class="line">rdbcompression yes</span><br><span class="line"></span><br><span class="line"># rdb文件的名称</span><br><span class="line">dbfilename redis-6379.rdb</span><br><span class="line"></span><br><span class="line"># rdb文件保存目录</span><br><span class="line">dir ~&#x2F;redis&#x2F;</span><br></pre></td></tr></table></figure>

<h2 id="RDB的几个优点"><a href="#RDB的几个优点" class="headerlink" title="RDB的几个优点"></a>RDB的几个优点</h2><ol>
<li>与AOF方式相比，通过rdb文件恢复数据比较快。</li>
<li>rdb文件非常紧凑，适合于数据备份。</li>
<li>通过RDB进行数据备，由于使用子进程生成，所以对Redis服务器性能影响较小。</li>
</ol>
<h2 id="RDB的几个缺点"><a href="#RDB的几个缺点" class="headerlink" title="RDB的几个缺点"></a><strong>RDB的几个缺点</strong></h2><ol>
<li>如果服务器宕机的话，采用<code>RDB</code>的方式会造成某个时段内数据的丢失，比如我们设置10分钟同步一次或5分钟达到1000次写入就同步一次，那么如果还没达到触发条件服务器就死机了，那么这个时间段的数据会丢失。</li>
<li>使用save命令会造成服务器阻塞，直接数据同步完成才能接收后续请求。</li>
<li>使用bgsave命令在forks子进程时，如果数据量太大，forks的过程也会发生阻塞，另外，forks子进程会耗费内存。</li>
</ol>
<h1 id="AOF"><a href="#AOF" class="headerlink" title="AOF"></a>AOF</h1><p>聊完了<code>RDB</code>,来聊聊<code>Redis</code>的另外一个持久化方式：<code>AOF(Append-only file)</code>。</p>
<p>与<code>RDB</code>存储某个时刻的快照不同，<code>AOF</code>持久化方式会记录客户端对服务器的每一次写操作命令，并将这些写操作以<code>Redis</code>协议追加保存到以后缀为<code>aof</code>文件末尾，在Redis服务器重启时，会加载并运行<code>aof</code>文件的命令，以达到恢复数据的目的。</p>
<p><img src="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_6.jpg" alt="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_6.jpg"></p>
<h2 id="开启AOF持久化方式"><a href="#开启AOF持久化方式" class="headerlink" title="开启AOF持久化方式"></a>开启AOF持久化方式</h2><p>Redis默认不开启AOF持久化方式，我们可以在配置文件中开启并进行更加详细的配置，如下面的redis.conf文件：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"># 开启aof机制</span><br><span class="line">appendonly yes</span><br><span class="line"></span><br><span class="line"># aof文件名</span><br><span class="line">appendfilename &quot;appendonly.aof&quot;</span><br><span class="line"></span><br><span class="line"># 写入策略,always表示每个写操作都保存到aof文件中,也可以是everysec或no</span><br><span class="line">appendfsync always</span><br><span class="line"></span><br><span class="line"># 默认不重写aof文件</span><br><span class="line">no-appendfsync-on-rewrite no</span><br><span class="line"></span><br><span class="line"># 保存目录</span><br><span class="line">dir ~&#x2F;redis&#x2F;</span><br></pre></td></tr></table></figure>

<h2 id="三种写入策略"><a href="#三种写入策略" class="headerlink" title="三种写入策略"></a>三种写入策略</h2><p>在上面的配置文件中，我们可以通过<code>appendfsync</code>选项指定写入策略,有三个选项</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">appendfsync always</span><br><span class="line"># appendfsync everysec</span><br><span class="line"># appendfsync no</span><br></pre></td></tr></table></figure>

<p>在上面的配置文件中，我们可以通过<code>appendfsync</code>选项指定写入策略,有三个选项</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">appendfsync always</span><br><span class="line"># appendfsync everysec</span><br><span class="line"># appendfsync no</span><br></pre></td></tr></table></figure>

<h3 id="1-always"><a href="#1-always" class="headerlink" title="1. always"></a>1. always</h3><p>客户端的每一个写操作都保存到<code>aof</code>文件当，这种策略很安全，但是每个写请注都有IO操作，所以也很慢。</p>
<h3 id="2-everysec"><a href="#2-everysec" class="headerlink" title="2. everysec"></a>2. everysec</h3><p><code>appendfsync</code>的默认写入策略，每秒写入一次<code>aof</code>文件，因此，最多可能会丢失1s的数据。</p>
<h3 id="3-no"><a href="#3-no" class="headerlink" title="3. no"></a>3. no</h3><p><code>Redis</code>服务器不负责写入<code>aof</code>，而是交由操作系统来处理什么时候写入<code>aof</code>文件。更快，但也是最不安全的选择，不推荐使用。</p>
<h2 id="AOF文件重写"><a href="#AOF文件重写" class="headerlink" title="AOF文件重写"></a>AOF文件重写</h2><p>AOF将客户端的每一个写操作都追加到<code>aof</code>文件末尾，比如对一个key多次执行incr命令，这时候，<code>aof</code>保存每一次命令到aof文件中，aof文件会变得非常大。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">incr num 1</span><br><span class="line">incr num 2</span><br><span class="line">incr num 3</span><br><span class="line">incr num 4</span><br><span class="line">incr num 5</span><br><span class="line">incr num 6</span><br><span class="line">...</span><br><span class="line">incr num 100000</span><br></pre></td></tr></table></figure>

<p>aof文件太大，加载aof文件恢复数据时，就会非常慢，为了解决这个问题，Redis支持aof文件重写，通过重写aof，可以生成一个恢复当前数据的最少命令集，比如上面的例子中那么多条命令，可以重写为：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">set</span> num 100000</span><br></pre></td></tr></table></figure>

<p>aof文件是一个二进制文件，并不是像上面的例子一样，直接保存每个命令，而使用Redis自己的格式，上面只是方便演示。</p>
<h2 id="两种重写方式"><a href="#两种重写方式" class="headerlink" title="两种重写方式"></a>两种重写方式</h2><p>通过在<code>redis.conf</code>配置文件中的选项<code>no-appendfsync-on-rewrite</code>可以设置是否开启重写，这种方式会在每次<code>fsync</code>时都重写，影响服务器性能，因此默认值为no，不推荐使用。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 默认不重写aof文件</span><br><span class="line">no-appendfsync-on-rewrite no</span><br></pre></td></tr></table></figure>

<p>客户端向服务器发送<code>bgrewriteaof</code>命令，也可以让服务器进行AOF重写。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 让服务器异步重写追加aof文件命令</span></span><br><span class="line">&gt; bgrewriteaof</span><br></pre></td></tr></table></figure>

<p><strong>AOF重写方式也是异步操作</strong>，即如果要写入aof文件，则Redis主进程会forks一个子进程来处理，如下所示：</p>
<p><img src="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_7.jpg" alt="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_7.jpg"></p>
<h3 id="重写aof文件的好处"><a href="#重写aof文件的好处" class="headerlink" title="重写aof文件的好处"></a>重写aof文件的好处</h3><ol>
<li>压缩aof文件，减少磁盘占用量。</li>
<li>将aof的命令压缩为最小命令集，加快了数据恢复的速度。</li>
</ol>
<h2 id="AOF文件损坏"><a href="#AOF文件损坏" class="headerlink" title="AOF文件损坏"></a>AOF文件损坏</h2><p>在写入aof日志文件时，如果Redis服务器宕机，则aof日志文件文件会出格式错误，在重启Redis服务器时，Redis服务器会拒绝载入这个aof文件，可以通过以下步骤修复aof并恢复数据。</p>
<ol>
<li><p>备份现在aof文件，以防万一。</p>
</li>
<li><p>使用<code>redis-check-aof</code>命令修复aof文件，该命令格式如下：</p>
 <figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 修复aof日志文件</span></span><br><span class="line">$ redis-check-aof -fix file.aof</span><br></pre></td></tr></table></figure></li>
<li><p>重启Redis服务器，加载已经修复的aof文件，恢复数据。</p>
</li>
</ol>
<h2 id="AOF的优点"><a href="#AOF的优点" class="headerlink" title="AOF的优点"></a>AOF的优点</h2><p>AOF只是追加日志文件，因此对服务器性能影响较小，速度比RDB要快，消耗的内存较少。</p>
<h2 id="AOF的缺点"><a href="#AOF的缺点" class="headerlink" title="AOF的缺点"></a>AOF的缺点</h2><ol>
<li>AOF方式生成的日志文件太大，即使通过AFO重写，文件体积仍然很大。</li>
<li>恢复数据的速度比RDB慢。</li>
</ol>
<h1 id="选择RDB还是AOF呢？"><a href="#选择RDB还是AOF呢？" class="headerlink" title="选择RDB还是AOF呢？"></a>选择RDB还是AOF呢？</h1><p>通过上面的介绍，我们了解了RDB与AOF各自的优点与缺点，到底要如何选择呢？</p>
<p>通过下面的表示，我们可以从几个方面对比一下RDB与AOF,在应用时，要根本自己的实际需求，选择RDB或者AOF，其实，如果想要数据足够安全，可以两种方式都开启，但两种持久化方式同时进行IO操作，会严重影响服务器性能，因此有时候不得不做出选择。</p>
<p><img src="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_8.jpg" alt="https://gitee.com/littlefxc/oss/raw/master/images/redis_rdb_aof_8.jpg"></p>
<p>当RDB与AOF两种方式都开启时，Redis会优先使用AOF日志来恢复数据，因为AOF保存的文件比RDB文件更完整。</p>
<h1 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h1><p>上面讲了一大堆<code>Redis</code>的持久化机制的知识，其实，如果你只是单纯把<code>Redis</code>作为缓存服务器，那么可以完全不用考虑持久化，但是，在如今的大多数服务器架构中，<code>Redis</code>的单单只是扮演一个缓存服务器的角色，还可以作为数据库，保存我们的业务数据，此时，我们则需要好好了解有关<code>Redis</code>持久化策略的区别与选择。</p>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="post-tags">
              <a href="/blog/tags/redis/" rel="tag"># redis</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/blog/2020/11/11/Hive%E9%9B%86%E6%88%90HBase-%E8%AF%A6%E8%A7%A3/" rel="prev" title="Hive集成HBase 详解">
                  <i class="fa fa-chevron-left"></i> Hive集成HBase 详解
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/blog/2021/01/09/%E4%BB%80%E4%B9%88%E6%98%AF%E5%80%92%E6%8E%92%E7%B4%A2%E5%BC%95/" rel="next" title="什么是倒排索引?">
                  什么是倒排索引? <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>







<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      const activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      const commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>
</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">一年春又来</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/mist/" class="theme-link" rel="noopener" target="_blank">NexT.Mist</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js"></script>
<script src="/blog/js/utils.js"></script><script src="/blog/js/motion.js"></script><script src="/blog/js/schemes/muse.js"></script><script src="/blog/js/next-boot.js"></script>

  
<script src="/blog/js/local-search.js"></script>






  





</body>
</html>
